// def2txt.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

#pragma pack(push,1)
typedef struct structHeader
{
	unsigned char		nMaxCode;
	unsigned long		aOffset[27];
} HEADER;
#pragma pack(pop)

typedef struct structCode
{
	unsigned char		nMaSize;
	unsigned char		nZiSize;
	char				szMa[256];
	wchar_t				szZi[128];
	unsigned long		nRate;
} CODE;

//using namespace std;
HEADER g_sHeader = { 0 };

bool g_bCompile = false;
bool g_bUnicode = false;
FILE *fin, *fout;

void def2txt(void)
{
    //	Read the header
	fread(&g_sHeader, sizeof(g_sHeader), 1, fin);
	printf("Max Code: %d\n", g_sHeader.nMaxCode);

    unsigned int nCurOffset = 0;
	wchar_t szTmp[128];
	CODE code;

	while (nCurOffset != g_sHeader.aOffset[26])
    {
		fread(&code.nMaSize, 1, 1, fin);
		fread(&code.nZiSize, 1, 1, fin);
		fread(code.szMa, code.nMaSize, 1, fin);
		code.szMa[code.nMaSize] = 0;
		fread(code.szZi, code.nZiSize, 1, fin);
		fread(&code.nRate, 4, 1, fin);

		nCurOffset += code.nMaSize + code.nZiSize + 6;

		if (g_bUnicode)
		{
			MultiByteToWideChar(CP_ACP, NULL, code.szMa, code.nMaSize + 1, szTmp, 128);
			_ftprintf(fout, _T("%s%s\n"), code.szZi, szTmp);
		}
		else
		{
			char *p = (char *)szTmp;
			WideCharToMultiByte(CP_OEMCP, NULL, code.szZi, code.nZiSize, p, 256, NULL, NULL);
			fprintf(fout, ("%s%s\n"), p, code.szMa);
		}
    }
}

void txt2def(void)
{
	g_sHeader.nMaxCode = 0;
	memset(g_sHeader.aOffset, 0, sizeof(g_sHeader.aOffset));

	//	Write the header
    fwrite(&g_sHeader, sizeof(g_sHeader), 1, fout);

	_TCHAR szLine[1024];// = _T("工안녕a");
	CODE code = { 0 };
	int i, len;
    unsigned int nCurOffset = 0;

	while (!feof(fin))
	{
		if (_fgetts(szLine, 1024, fin) == NULL)
			continue;

		len = _tcslen(szLine);

		if (len < 3)
			continue;

		for (i = 0; i < len; i++)
		{
			if (szLine[i] < 0xff)
				break;
		}

		_tcsncpy(code.szZi, szLine, i);
		code.szZi[i] = 0;
		code.nZiSize = (i + 1) * 2;

		//_tcsncpy(code.szZi, szLine, i);
		code.nMaSize = len - i - 1;
		WideCharToMultiByte(CP_OEMCP, NULL, szLine + i, code.nMaSize, code.szMa, 256, NULL, NULL);

		fwrite(&code.nMaSize, 1, 1, fout);
		fwrite(&code.nZiSize, 1, 1, fout);
		fwrite(code.szMa, code.nMaSize, 1, fout);
		fwrite(code.szZi, code.nZiSize, 1, fout);
		fwrite(&code.nRate, 4, 1, fout);

		nCurOffset += code.nMaSize + code.nZiSize + 6;

		g_sHeader.aOffset[*code.szMa - 96] = nCurOffset;
	}

	g_sHeader.aOffset[26] = nCurOffset;

	for (i = 25; i > 0; i--)
	{
		if (!g_sHeader.aOffset[i])
			g_sHeader.aOffset[i] = g_sHeader.aOffset[i + 1];
	}

	//	Update the header
    fseek(fout, 0L, SEEK_SET);
    fwrite(&g_sHeader, sizeof(g_sHeader), 1, fout);
}

int _tmain(int argc, _TCHAR* argv[])
{
    if (argc < 3)
    {
        printf("\nDEF2TXT v0.1b DayHand custom DEF file de-compiler\n");
        printf("Tommy Lau All Rights Reserved. (C)2009\n");
        printf("E-Mail/MSN: tommy@gen-new.com\n\n");
        printf("\tUsage: DEF2TXT <src> <dst>\r\n");
        exit(1);
    }

    if (argc >= 4 && !_tcsicmp(argv[3], _T("C")))
        g_bCompile = true;

    if (argc >= 4 && !_tcsicmp(argv[3], _T("U")))
        g_bUnicode = true;

    if (g_bCompile)
    {
		fin = _tfopen(argv[1], _T("r, ccs=UNICODE"));
		fout = _tfopen(argv[2], _T("wb"));
    }
    else
    {
		fin = _tfopen(argv[1], _T("rb"));
		if (g_bUnicode)
			fout = _tfopen(argv[2], _T("w, ccs=UNICODE"));
		else
			fout = _tfopen(argv[2], _T("w"));
    }

	if (fin == NULL || fout == NULL)
	{
		printf("Open file error.\n");
		fclose(fin);
		fclose(fout);
		exit(2);
	}

    if (g_bCompile)
        txt2def();
    else
        def2txt();

	fclose(fin);
	fclose(fout);

	return 0;
}
